package com.link_with_health.webSocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.link_with_health.config.ApplicationContextAwareGetBean;
import com.link_with_health.model.WaitingQueueEntity;
import com.link_with_health.service.WaitingQueueService;
import com.link_with_health.utils.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
import java.util.HashMap;

@ServerEndpoint("/waitingQueue/{waitingQueueId}/{userId}")
@Component
@Scope("prototype")
public class WaitingQueueServer {
    private static final Logger logger = LoggerFactory
            .getLogger(WaitingQueueServer.class);

    private WaitingQueueService service;

    /**
     * concurrent包的线程安全Set，用来存放每个
     * 客户端对应的MyWebSocket对象。
     */
    private static ConcurrentHashMap<String, Map<String,Session>>
            sessionPool = new ConcurrentHashMap<>();

    /**
     * 根据inquiry id 保存候诊信息
     */
    private static ConcurrentHashMap<String, WaitingQueueEntity>
            queueMsgPool = new ConcurrentHashMap<>();

    private Session session;
    /**
     * 用户连接ws的id，为user表上的用户id
     */
    private String userId;

    /**
     * 候诊信息id，在对候诊室内的用户进行广播时
     * 用来获取候诊室用户的会话
     */
    private String waitingQueueId;

    private Map<String,Session> queue;

    private WaitingQueueEntity queueMsg;

    @OnOpen
    public void onOpen (Session session
            , @PathParam("waitingQueueId") String waitingQueueId
            , @PathParam("userId") String userId){
        this.session = session;
        this.waitingQueueId = waitingQueueId;
        this.userId = userId;
        //初始化候诊信息
        initQueue();
        logger.info("user " + userId + " connect "
                + "to " + "waitingQueue: " + waitingQueueId);

    }

    @OnClose
    public void onClose (){
        System.out.println("user " + userId
                + " close to connection: "
                + "\nfrom waitingQueue: " + waitingQueueId);
    }

    @OnMessage
    public void onMessage (String message,Session session){
        try {
            this.sendMessage(message);
            logger.info(message);
        } catch (IOException e) {
            logger.error("[send message for patient failed]",e);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("连接异常...");
        logger.error("[error for connection]",error);
    }

    /**
     * 初始化候诊信息
     */
    private synchronized void initQueue(){

        service = ApplicationContextAwareGetBean
                .getBean(WaitingQueueService.class);
        //判断是否存在候诊连接信息
        if(!sessionPool.containsKey(waitingQueueId))
            queue = new HashMap<String,Session>();
        else
            queue = sessionPool.get(waitingQueueId);
        //将会话信息存到同一候诊室的map中
        queue.put(userId,session);
        sessionPool.put(waitingQueueId,queue);

        Long id = Long.parseLong(waitingQueueId);

        if (!queueMsgPool.containsKey(waitingQueueId)) {
            queueMsg = service.getWaitingQueueById(id);
            queueMsgPool.put(waitingQueueId, queueMsg);
        }
        queueMsg = queueMsgPool.get(waitingQueueId);
    }

    /**
     * 对候诊室内的用户发送更新后的信息
     * @param queueJson
     * @param queueId
     */
    public static void modifyQueue(String queueJson ,Long queueId){

        String id = String.valueOf(queueId);
        HashMap<String,Session> map = (HashMap<String, Session>)
                sessionPool.get(id);
        //遍历候诊室上的信息
        for(Map.Entry<String, Session> entry : map.entrySet()){
            try {
                entry.getValue().getBasicRemote().sendText(queueJson);
            } catch (IOException e) {
                logger.error("send update message fail \n"
                        + queueJson);
            }
        }

    }

    /**
     * 推送信息
     * @param jsonStr
     * @throws IOException
     */
    public void sendMessage(String jsonStr)
            throws IOException{
        JSONObject json = JSON.parseObject(jsonStr);
        queueMsg.setMaxAppointment(
           json.getInteger("maxAppointment"));
        queueMsg.setMaxQueue(
           json.getInteger("maxQueue"));
        queueMsg.setPatientQueue(
           json.getString("patientQueue"));
        queueMsg.setDoctorId(
                json.getLong("doctorId"));
        String queueId = String.valueOf(
                queueMsg.getQueueId());

        HashMap<String,Session> map = (HashMap<String, Session>)
                sessionPool.get(queueId);
        for(Map.Entry<String, Session> entry : map.entrySet()){
            entry.getValue().getBasicRemote().sendText(jsonStr);
        }

    }
}
